#import "TTCropImageViewController.h"
#import "UIView+TTFrame.h"
#import "NSString+TTExtension.h"

#pragma mark - Const - 布局
#define kInstructionsMargin 10
#define kInstructionsMarginTopAndBottom 15
#define kPanRightViewHeightAndBottomWidth 20
#define kPanRightViewWidthAndBottomHeight 6
#define kPanViewMaxHeight 25

#pragma mark - Const - 颜色
#define kBackgroundColor [UIColor colorWithRed:247.0 / 255 green:247.0 / 255 blue:247.0 / 255 alpha:1.0];

#pragma mark - Const - 系统常量
#define kScreenBounds [[UIScreen mainScreen] bounds]
#define kScreenWidth [[UIScreen mainScreen] bounds].size.width
#define kScreenHeight [[UIScreen mainScreen] bounds].size.height
#define kStatusBarMaxY CGRectGetMaxY([[UIApplication sharedApplication] statusBarFrame])
#define kNavigationBarMaxY CGRectGetMaxY(self.navigationController.navigationBar.frame)

@interface TTCropImageViewController () <UIGestureRecognizerDelegate>

// 文字
@property (nonatomic, strong) UILabel *instructionsLabel;
// 文字 与 图片分割线
@property (nonatomic, strong) UIView *separatorView;
// 展示图片View
@property (nonatomic, strong) UIImageView *imageView;
// 拖动的View
@property (nonatomic, strong) UIView *panView;
// 拖动右侧View
@property (nonatomic, strong) UIView *scaleXControlView;
// 拖动下方View
@property (nonatomic, strong) UIView *scaleYControlView;
// 图层View
@property (nonatomic, strong) UIImageView *coverImageView;

@property (nonatomic) CGRect cropRect;
@property (nonatomic) CGRect startRect;
@property (nonatomic) CGRect graphicsRect;

@end

@implementation TTCropImageViewController

#pragma mark - Lifecycle Methods
- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.instructionsLabel.text = self.instructions;
    self.view.backgroundColor = kBackgroundColor
    self.automaticallyAdjustsScrollViewInsets = false;
    
    [self setupAddSubviews];
    [self setupNavigationItems];
    [self setupLayoutViews];
}

#pragma mark - 初始化设置
#pragma mark 添加Views
- (void)setupAddSubviews {
    [self.view addSubview:self.imageView];
    [self.view addSubview: self.coverImageView];
    [self.view addSubview: self.panView];
    if (self.instructions.length) {
        [self.view addSubview: self.separatorView];
        [self.view addSubview:self.instructionsLabel];
    }
}

#pragma mark 设置NavigationItems
- (void)setupNavigationItems {
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Cancel" style:UIBarButtonItemStylePlain target:self action:@selector(didTapCancel)];
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStylePlain target:self action:@selector(didTapDone)];
}

#pragma mark 设置views frame
- (void)setupLayoutViews {
    
    // instructionsLabel
    CGFloat instructionsLabelX = kInstructionsMargin;
    CGFloat instructionsLabelY = kStatusBarMaxY;
    if (self.instructions.length) instructionsLabelY = instructionsLabelY + kInstructionsMarginTopAndBottom;
    if (self.navigationController.navigationBar) instructionsLabelY = instructionsLabelY + 44;
    CGFloat instructionsLabelWidth = kScreenWidth - kInstructionsMargin * 2;
    CGSize size = [self.instructions returnContentSizeWithFont:self.instructionsLabel.font width:instructionsLabelWidth];
    CGFloat instructionsLabelHeight = size.height;
    self.instructionsLabel.frame = CGRectMake(instructionsLabelX, instructionsLabelY, instructionsLabelWidth, instructionsLabelHeight);
    
    // separatorView
    CGFloat separatorViewX = 0;
    CGFloat separatorViewY = CGRectGetMaxY(self.instructionsLabel.frame) + kInstructionsMarginTopAndBottom;
    CGFloat separatorViewWidth = kScreenWidth;
    CGFloat separatorViewHeight = 1;
    self.separatorView.frame = CGRectMake(separatorViewX, separatorViewY, separatorViewWidth, separatorViewHeight);
    
    // coverImageView
    CGFloat contentImageViewX = 0;
    CGFloat contentImageViewY = 0;
    CGFloat contentImageViewWidth = kScreenWidth;
    CGFloat contentImageViewHeight = kScreenHeight;
    self.coverImageView.frame = CGRectMake(contentImageViewX, contentImageViewY, contentImageViewWidth, contentImageViewHeight);
    
    // 模糊图层的大小
    CGFloat graphicsX = 0;
    CGFloat graphicsY = 0;
    CGFloat graphicsWidth = self.coverImageView.width;
    CGFloat graphicsHeight = self.coverImageView.height;
    self.graphicsRect = CGRectMake(graphicsX, graphicsY, graphicsWidth, graphicsHeight);
    
    // imageView
    CGSize imageToCropSize = self.imageToCrop.size;
    CGFloat instructionsLabelMaxY = CGRectGetMaxY(self.instructionsLabel.frame);
    if (self.instructions.length) instructionsLabelMaxY = instructionsLabelMaxY + kInstructionsMarginTopAndBottom;
    CGFloat imageViewMaxHeight = kScreenHeight - instructionsLabelMaxY;
    CGFloat imageViewWidth = kScreenWidth;
    CGFloat scale = imageToCropSize.width / imageViewWidth;
    CGFloat imageViewHeight = imageToCropSize.height / scale;
    if (imageViewHeight > imageViewMaxHeight) {
        imageViewHeight = imageViewMaxHeight;
        scale = imageToCropSize.height / imageViewHeight;
        imageViewWidth = imageToCropSize.width / scale;
    }
    CGFloat imageViewX = (kScreenWidth - imageViewWidth) * 0.5;
    CGFloat imageViewY = (imageViewMaxHeight - imageViewHeight) * 0.5 + instructionsLabelMaxY;
    self.imageView.frame = CGRectMake(imageViewX, imageViewY, imageViewWidth, imageViewHeight);
    
    // panView
    CGFloat panViewWidth = imageViewWidth;
    CGFloat panViewHeight = self.imageView.width * 0.5;
    if (panViewHeight > imageViewHeight) { panViewHeight = imageViewHeight; }
    CGFloat panViewX = imageViewX;
    CGFloat panViewY = (imageViewHeight - panViewHeight) * 0.5 + imageViewY;
    self.panView.frame = CGRectMake(panViewX, panViewY, panViewWidth, panViewHeight);
    
    // 模糊图层中显示区域的大小
    CGFloat cropRectX = panViewX;
    CGFloat cropRectY = (self.imageView.height - self.panView.height) * 0.5 + self.imageView.y;
    CGFloat cropRectWidth = panViewWidth;
    CGFloat cropRectHeight = panViewHeight;
    self.cropRect = CGRectMake(cropRectX, cropRectY, cropRectWidth, cropRectHeight);
    
    // scaleXControlView(右)
    CGFloat scaleXControlViewWidth = kPanRightViewWidthAndBottomHeight;
    CGFloat scaleXControlViewHeight = kPanRightViewHeightAndBottomWidth;
    CGFloat scaleXControlViewX = panViewWidth - scaleXControlViewWidth;
    CGFloat scaleXControlViewY = (panViewHeight - scaleXControlViewHeight) * 0.5;
    self.scaleXControlView.frame = CGRectMake(scaleXControlViewX, scaleXControlViewY, scaleXControlViewWidth, scaleXControlViewHeight);
    
    // scaleYControlView(下)
    CGFloat scaleYControlViewWidth = kPanRightViewHeightAndBottomWidth;
    CGFloat scaleYControlViewHeight = kPanRightViewWidthAndBottomHeight;
    CGFloat scaleYControlViewX = (panViewWidth - scaleYControlViewWidth) * 0.5;
    CGFloat scaleYControlViewY = panViewHeight - scaleYControlViewHeight;
    self.scaleYControlView.frame = CGRectMake(scaleYControlViewX, scaleYControlViewY, scaleYControlViewWidth, scaleYControlViewHeight);

    [self drawShadeLayer];
}

#pragma mark - Gesture Recognizer helpers
#pragma mark 拖动X方向
- (void)didScaleX:(UIPanGestureRecognizer *)recognizer {
    if (recognizer.state == UIGestureRecognizerStateBegan) {
        self.startRect = self.panView.frame;
    } else if (recognizer.state == UIGestureRecognizerStateChanged) {
        [self setScaleXWithTranslation:[recognizer translationInView:self.panView]];
    }
}

#pragma mark 拖动Y方向
- (void)didScaleY:(UIPanGestureRecognizer *)recognizer {
    if (recognizer.state == UIGestureRecognizerStateBegan) {
        self.startRect = self.panView.frame;
    } else if (recognizer.state == UIGestureRecognizerStateChanged) {
        [self setScaleYWithTranslation:[recognizer translationInView:self.panView]];
    }
}

#pragma mark 拖动view
- (void)didPan:(UIPanGestureRecognizer *)recognizer {
    if (recognizer.state == UIGestureRecognizerStateBegan) {
        self.startRect = self.panView.frame;
    } else if (recognizer.state == UIGestureRecognizerStateChanged) {
        CGPoint point = [recognizer translationInView:self.panView];
        [self setRectWithTranslation:point];
    }
}

- (void)didLong:(UILongPressGestureRecognizer *)recognizer {
    if (recognizer.state == UIGestureRecognizerStateBegan) {
        [self didTapDone];
    }
}

- (void)setScaleXWithTranslation:(CGPoint)translation {
    CGRect newRect = self.startRect;
    CGFloat changedWidth = newRect.size.width + translation.x;
    if (translation.x > 0) {
        CGRect rect = [self.view convertRect:self.panView.frame toView:self.imageView];
        if ((rect.size.height + rect.origin.y + 1 ) > self.imageView.height) {
            changedWidth = (self.imageView.height - rect.origin.y) * 2;
        }
        
        if (changedWidth + rect.origin.x > self.imageView.width) {
            changedWidth = self.imageView.width - rect.origin.x;
        }
        
        newRect.size.width = MIN(changedWidth, self.imageView.width);
    } else {
        newRect.size.width = MAX(changedWidth, kPanViewMaxHeight * 2);
    }
    newRect.size.height = newRect.size.width * 0.5;
    
    self.cropRect = newRect;
    self.panView.frame = newRect;
    [self drawShadeLayer];
    [self resetScaleVeiws];
}

- (void)setScaleYWithTranslation:(CGPoint)translation {
    CGRect newRect = self.startRect;
    CGFloat changedHeight = newRect.size.height + translation.y;
    if (translation.y > 0) {
        CGRect rect = [self.view convertRect:self.panView.frame toView:self.imageView];
        if ((rect.size.width + rect.origin.x + 2 ) > self.imageView.width) {
            changedHeight = (self.imageView.width - rect.origin.x) * 0.5;
        }
        if (changedHeight + rect.origin.y > self.imageView.height) {
            changedHeight = self.imageView.height - rect.origin.y;
        }
        
        newRect.size.height = MIN(changedHeight, self.imageView.width * 0.5);
    } else {
        newRect.size.height = MAX(changedHeight, kPanViewMaxHeight);
    }
    newRect.size.width = newRect.size.height * 2;
    
    self.cropRect = newRect;
    self.panView.frame = newRect;
    [self drawShadeLayer];
    [self resetScaleVeiws];
}

- (void)resetScaleVeiws {
    self.scaleYControlView.x = (self.panView.width - self.scaleYControlView.width) * 0.5;
    self.scaleYControlView.y = self.panView.height - self.scaleYControlView.height;

    self.scaleXControlView.x = self.panView.width - self.scaleXControlView.width ;
    self.scaleXControlView.y = (self.panView.height - self.scaleXControlView.height)* 0.5;
}

- (void)setRectWithTranslation:(CGPoint)translation {
    CGRect newRect = self.startRect;
    
    newRect.origin.x = MAX((newRect.origin.x + translation.x), self.imageView.x );
    if (translation.x > 0) {
        newRect.origin.x = MIN((newRect.origin.x + translation.x), (self.imageView.x + self.imageView.width - self.panView.width));
    }
    
    newRect.origin.y = MAX((newRect.origin.y + translation.y), self.imageView.y);
    if (translation.y > 0) {
        newRect.origin.y = MIN((newRect.origin.y + translation.y), (self.imageView.y + self.imageView.height - self.panView.height));
    }
    self.cropRect = newRect;
    self.panView.frame = newRect;
    [self drawShadeLayer];
}

// 渲染模糊层中显示的部分
- (void)drawShadeLayer {
    // 开启位图上下文
    UIGraphicsBeginImageContextWithOptions(self.graphicsRect.size, NO, 0.f);
    // 获取当前上下文
    CGContextRef context = UIGraphicsGetCurrentContext();
    // 首先渲染一个模糊的图层
    [[[UIColor whiteColor] colorWithAlphaComponent:0.7] setFill];
    UIRectFill(self.graphicsRect);
    
    // 在上下文中设置矩形边框的颜色
    CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] colorWithAlphaComponent:0.5].CGColor);
    // 设置矩形边框的大小
    CGContextStrokeRect(context, self.cropRect);
    
    // 用透明颜色渲染显示区域(矩形边框), 这样可以清晰可见
    [[UIColor clearColor]setFill];
    UIRectFill(CGRectInset(self.cropRect, 1, 1) );
    // 获取上下文中的image
    self.coverImageView.image = UIGraphicsGetImageFromCurrentImageContext();
    // 关闭上下文
    UIGraphicsEndImageContext();
}

#pragma mark - UI Action Methods
- (void)didTapCancel {
    [self.navigationController dismissViewControllerAnimated:YES completion:nil];
}

- (void)didTapDone {
    UIActivityIndicatorView *spinnerView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:(UIActivityIndicatorViewStyleWhite)];
    [self.view addSubview:spinnerView];
    [spinnerView startAnimating];
    
    CGFloat spinnerViewWidth = (kScreenWidth - spinnerView.width) / 2;
    CGFloat spinnerViewHeight = (kScreenHeight - spinnerView.height) / 2;
    spinnerView.center = CGPointMake(spinnerViewWidth, spinnerViewHeight);
    
    CGFloat scale = self.imageToCrop.size.width / self.imageView.width;
    CGRect rect = [self.view convertRect:self.panView.frame toView:self.imageView];
    NSInteger startX = rect.origin.x * scale;
    NSInteger startY = rect.origin.y * scale;
    NSInteger endX = (rect.origin.x + rect.size.width) * scale;
    NSInteger endY = (rect.origin.y + rect.size.height) * scale;
    [spinnerView stopAnimating];
    if ([self.delegate respondsToSelector:@selector(cropViewController:didFinishCropStartX:endX:startY:endY:)]) {
        [self.delegate cropViewController:self didFinishCropStartX:startX endX:endX startY:startY endY:endY];
        return;
    }
    [self didTapCancel];
}

#pragma mark - 懒加载Views
// 文字
- (UILabel *)instructionsLabel {
    if (!_instructionsLabel) {
        _instructionsLabel = [[UILabel alloc] init];
        _instructionsLabel.numberOfLines = 0;
        _instructionsLabel.textAlignment = NSTextAlignmentCenter;
    }
    
    return _instructionsLabel;
}

// 文字 与 图片分割线
- (UIView *)separatorView {
    if (!_separatorView) {
        _separatorView = [[UIView alloc] init];
        _separatorView.backgroundColor = [UIColor colorWithRed:0.9137 green:0.9137 blue:0.9137 alpha:1.0];
    }
    
    return _separatorView;
}

// 展示图片View
- (UIImageView *)imageView {
    if (!_imageView) {
        _imageView = [[UIImageView alloc] initWithImage:self.imageToCrop];
        _imageView.contentMode = UIViewContentModeScaleAspectFit;
    }
    
    return _imageView;
}

// 拖动的View
- (UIView *)panView {
    if (!_panView) {
        _panView = [[UIView alloc] init];
        _panView.clipsToBounds = NO;
        _panView.backgroundColor = [UIColor clearColor];
        
        UIPanGestureRecognizer *panGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didPan:)];
        [panGestureRecognizer setMinimumNumberOfTouches:1];
        [panGestureRecognizer setMaximumNumberOfTouches:1];
        [_panView addGestureRecognizer:panGestureRecognizer];
        
        UILongPressGestureRecognizer *longGestureRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(didLong:)];
        longGestureRecognizer.minimumPressDuration = 2;
        [_panView addGestureRecognizer:longGestureRecognizer];
        
        [_panView addSubview:self.scaleXControlView];
        [_panView addSubview:self.scaleYControlView];
    }
    
    return _panView;
}

// 拖动下方View
- (UIView *)scaleYControlView {
    if (!_scaleYControlView) {
        _scaleYControlView = [[UIView alloc] init];
        _scaleYControlView.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.7f];
        
        UIPanGestureRecognizer *panYScaleGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didScaleY:)];
        [panYScaleGestureRecognizer setMinimumNumberOfTouches:1];
        [panYScaleGestureRecognizer setMaximumNumberOfTouches:1];
        [_scaleYControlView addGestureRecognizer:panYScaleGestureRecognizer];
    }
    
    return _scaleYControlView;
}

// 拖动下方View
- (UIView *)scaleXControlView {
    if (!_scaleXControlView) {
        _scaleXControlView = [[UIView alloc] init];
        _scaleXControlView.backgroundColor = [[UIColor whiteColor] colorWithAlphaComponent:0.7f];
        
        UIPanGestureRecognizer *panXScaleGestureRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(didScaleX:)];
        [panXScaleGestureRecognizer setMinimumNumberOfTouches:1];
        [panXScaleGestureRecognizer setMaximumNumberOfTouches:1];
        [_scaleXControlView addGestureRecognizer:panXScaleGestureRecognizer];
    }
    return _scaleXControlView;
}

// 图层View
- (UIImageView *)coverImageView {
    if (!_coverImageView) {
        _coverImageView = [[UIImageView alloc] init];
    }
    
    return _coverImageView;
}

@end
